package com.qdl.rym.util;

import com.alibaba.fastjson.JSONArray;
import com.qdl.rym.exception.BusinessException;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.util.CellRangeAddress;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.IntStream;

/**
 * @Description: ExcelUtil
 * @Author: ChenXueLi
 * @Date: 2018-12-11 21:34
 * 你是一段成熟的代码，要学会自己找bug
 */
public class ExcelUtil {

    /**
     * 解析表格数据
     * @param sheet 表格信息
     * @return List<Map<String, Object>>数据
     * @throws Exception 数据读取错误
     */
    public static List<Map<String, Object>> resolveExcel(Sheet sheet) throws Exception{
        return ExcelUtil.resolveExcel(sheet, 2, 1);
    }

    /**
     * 解析表格数据
     * @param sheet 表格信息
     * @param dataRowNum 数据开始行数
     * @return List<Map<String, Object>>数据
     * @throws Exception 数据读取错误
     */
    public static List<Map<String, Object>> resolveExcel(Sheet sheet, int dataRowNum) throws Exception{
        return resolveExcel(sheet, dataRowNum, dataRowNum - 1);
    }

    /**
     * 解析表格数据
     * @param sheet 表格信息
     * @param dataRowNum 数据开始行数
     * @param fieldRowNum 字段行数
     * @return List<Map<String, Object>>数据
     * @throws Exception 数据读取错误
     */
    public static List<Map<String, Object>> resolveExcel(Sheet sheet, int dataRowNum, int fieldRowNum) throws Exception{
        List<Map<String, Object>> list = new ArrayList<>();

        // 获取字段信息
        Row fieldRow = sheet.getRow(fieldRowNum);
        if(fieldRow == null) {
            throw new BusinessException(-101, String.format("第%s行获取字段信息错误", fieldRowNum));
        }
        int maxCellNum = fieldRow.getLastCellNum();
        if(maxCellNum == -1) {
            throw new BusinessException(-102, String.format("第%s行获取字段信息错误", fieldRowNum));
        }

        List<String> fieldList = new ArrayList<>();
        for(int i = 0; i < maxCellNum; i++) {
            String field = ExcelUtil.getCellValue(fieldRow, i);
            fieldList.add(field);
        }

        // 遍历表格行数据
        for(int i = dataRowNum; i <= sheet.getLastRowNum(); i++) {
            // 获取行数据
            Row row = sheet.getRow(i);
            // 判断当前行是否为空
            if(row != null) {
                Map<String, Object> map = new HashMap<>();
                map.put("excel_row", i + 1);
                // 遍历第i行的列数据
                for(int j = 0; j < maxCellNum; j++) {
                    // 获取列数据的内容
                    String content = ExcelUtil.getCellValue(row, j);
                    // 匹配的字段数据存放
                    map.put(fieldList.get(j), content);
                }
                // 添加到结果集中
                list.add(map);
            }
        }
        return list;
    }

    /**
     * 解析表格数据
     * @param sheet 表格信息
     * @param clazz 实体类class
     * @param <T> 实体类参数
     * @return List<Map<String, Object>>数据
     * @throws Exception 数据读取错误
     */
    public static <T> List<T> resolveExcel(Sheet sheet, Class<T> clazz) throws Exception{
        return ExcelUtil.resolveExcel(sheet, 2, clazz);
    }

    /**
     * 解析表格数据
     * @param sheet 表格信息
     * @param dataRowNum 数据开始行数
     * @param clazz 实体类class
     * @param <T> 实体类参数
     * @return List<Map<String, Object>>数据
     * @throws Exception 数据读取错误
     */
    public static <T> List<T> resolveExcel(Sheet sheet, int dataRowNum, Class<T> clazz) throws Exception{
        List<Map<String, Object>> list = ExcelUtil.resolveExcel(sheet, dataRowNum, dataRowNum - 1);
        String jsonData = JSONArray.toJSONString(list);
        return JSONArray.parseArray(jsonData, clazz);
    }

    /**
     * 解析表格数据
     * @param sheet 表格信息
     * @param dataRowNum 数据开始行数
     * @param fieldRowNum 字段行数
     * @param clazz 实体类class
     * @param <T> 实体类参数
     * @return List<Map<String, Object>>数据
     * @throws Exception 数据读取错误
     */
    public static <T> List<T> resolveExcel(Sheet sheet, int dataRowNum, int fieldRowNum, Class<T> clazz) throws Exception{
        List<Map<String, Object>> list = ExcelUtil.resolveExcel(sheet, dataRowNum, fieldRowNum);
        String jsonData = JSONArray.toJSONString(list);
        return JSONArray.parseArray(jsonData, clazz);
    }

    /**
     * 获取单元格的内容
     * @param row 行对象
     * @param index 列
     * @return 字符串对象
     */
    private static String getCellValue(Row row, int index) {
        // 获取单元格信息
        Cell cell = row.getCell(index);
        if(cell != null) {
            return ExcelUtil.getCellValue(cell);
        }
        return "";
    }

    /**
     * 获取单元格的值
     * @param cell 单元格
     * @return 字符串对象
     */
    public static String getCellValue(Cell cell){
        String content = "";
        switch (cell.getCellType()){
            case STRING:
                content = cell.getStringCellValue();
                break;
            case BOOLEAN:
                content = String.valueOf(cell.getBooleanCellValue());
                break;
            case FORMULA:
                content = cell.getCellFormula();
                break;
            case NUMERIC:
                content = String.valueOf(cell.getNumericCellValue());
                break;
            case ERROR:
            case BLANK:
            case _NONE:
            default:
        }
        return content;
    }

    /**
     * 判断sheet页中是否含有合并单元格
     * @param sheet 表格信息
     * @return 存在true， 不存在false
     */
    private static boolean hasMerged(Sheet sheet) {
        return sheet.getNumMergedRegions() > 0;
    }

    /**
     * 合并单元格
     * @param sheet 表格信息
     * @param firstRow 开始行
     * @param lastRow 结束行
     * @param firstCol 开始列
     * @param lastCol 结束列
     */
    private static void mergeRegion(Sheet sheet, int firstRow, int lastRow, int firstCol, int lastCol) {
        sheet.addMergedRegion(new CellRangeAddress(firstRow, lastRow, firstCol, lastCol));
    }

    /**
     * 判断指定的单元格是否是合并单元格
     * @param sheet 表格信息
     * @param row 行下标
     * @param column 列下标
     * @return
     */
    private boolean isMergedRegion(Sheet sheet, int row, int column) {
        int sheetMergeCount = sheet.getNumMergedRegions();
        return IntStream.range(0, sheetMergeCount).mapToObj(sheet::getMergedRegion).findFirst().filter(cell -> row >= cell.getFirstRow() && row <= cell.getLastRow() && column >= cell.getFirstColumn() && column <= cell.getLastColumn()).isPresent();
    }

    /**
     * 获取合并单元格的值
     * @param sheet
     * @param row
     * @param column
     * @return
     */
    public static String getMergedRegionValue(Sheet sheet, int row, int column){
        int sheetMergeCount = sheet.getNumMergedRegions();
        for(int i = 0 ; i < sheetMergeCount ; i++){
            // 获取合并单元格信息
            CellRangeAddress cell = sheet.getMergedRegion(i);
            // 获取首列
            int firstColumn = cell.getFirstColumn();
            // 获取最后一列
            int lastColumn = cell.getLastColumn();
            // 获取首行
            int firstRow = cell.getFirstRow();
            // 获取最后一行
            int lastRow = cell.getLastRow();
            if(row >= firstRow && row <= lastRow){
                if(column >= firstColumn && column <= lastColumn){
                    Row fRow = sheet.getRow(firstRow);
                    Cell fCell = fRow.getCell(firstColumn);
                    return getCellValue(fCell) ;
                }
            }
        }

        return null ;
    }

}
